﻿using System;
using Internal.Runtime.Models;
using Runtime.Services.Battle;
using Runtime.Services.Battle.Entity;
using UnityEngine;

namespace Runtime.Models {

    /// <summary>
    /// 目标数据
    /// </summary>
    public interface IDFR_BattleAttackTargetModelTD : IDFR_BattleAttackTargetModelBase {

        public delegate void DeadDelegate();

        event DeadDelegate OnDead;

        new IDFR_BattleAttackTargetModelTDSetter AsSetter();

        IDFR_BattleMovementModel AsMovement();

        /// <summary>
        /// 是否已经抵达目的地
        /// </summary>
        IReadOnlyBoolData IsArrived { get; }

        /// <summary>
        /// 路径ID
        /// </summary>
        DFR_BattleWayID WayID { get; }
    }

    public interface IDFR_BattleAttackTargetModelTDSetter : IDFR_BattleAttackTargetModelBaseSetter, IDFR_BattleAttackTargetModelTD {

        IDFR_BattleData WayPosition { get; }

        void Arrived();

        void Dead();
    }

    public abstract class DFR_BattleAttackTargetModelTD : DFR_BattleAttackTargetModelBase,
        IDFR_BattleAttackTargetModelTD, IDFR_BattleAttackTargetModelTDSetter, IDFR_BattleAttackTargetModelTDInternal,
        IDFR_BattleMovementModel, IDFR_BattleMovementModelInternl {

        public event IDFR_BattleAttackTargetModelTD.DeadDelegate OnDead;

        public new IDFR_BattleAttackTargetModelTDSetter AsSetter() => this;

        public IDFR_BattleMovementModel AsMovement() => this;

        [Autowired]
        private readonly IBoolData m_IsArrived;
        public IReadOnlyBoolData IsArrived => m_IsArrived;

        public DFR_BattleWayID WayID { get; private set; }

        [Autowired]
        private readonly IDFR_BattleData m_WayPosition;
        IDFR_BattleData IDFR_BattleAttackTargetModelTDSetter.WayPosition => m_WayPosition;
        protected IDFR_BattleData WayPosition => m_WayPosition;

        protected override bool IsEnabled => base.IsEnabled && !m_IsArrived.Value;

        private F64 m_LastWayPosition;
        F64 IDFR_BattleMovementModel.LastWayPosition => m_LastWayPosition;

        private Vector2F64 m_Offset;
        Vector2F64 IDFR_BattleMovementModel.Offset => m_Offset;

        DFR_BattleEntityInstanceID IDFR_BattleMovementModel.EntityInstanceID => EntityInstanceID;

        protected override DFR_BattleMapPosition MapPosition => BattleServiceTD.Instance.GetMapPosition(WayID, m_WayPosition.Value, false) + m_Offset;

        private DFR_BattleMapPosition m_LastMapPosition;
        protected override DFR_BattleMapPosition LastMapPosition => m_LastMapPosition + m_Offset;

        DFR_BattleMapPosition IDFR_BattleMovementModel.MapPosition => MapPosition;

        IDFR_ReadOnlyBattleData IDFR_BattleMovementModel.WayPosition => m_WayPosition;

        DFR_BattleMapPosition IDFR_BattleMovementModel.LastMapPosition => m_LastMapPosition;

        protected override void Dispose() {
            OnDead = null;
            base.Dispose();
        }

        protected override DFR_BattleMapPosition SupposeMove(F64 time) {
            var way = BattleServiceTD.Instance.GetWay(WayID);
            var forward = time * MoveSpeed.Value;
            var wayPosition = m_WayPosition.Value + forward;
            wayPosition = F64.Clamp(wayPosition, F64.Zero, way.Length);
            return BattleServiceTD.Instance.GetMapPosition(WayID, wayPosition, false) + m_Offset;
        }

        protected override Vector2F64 RenderOffset => m_Offset;

        void IDFR_BattleMovementModelInternl.SetLastPosition(F64 wayPosition, DFR_BattleMapPosition mapPosition) {
            m_LastWayPosition = wayPosition;
            m_LastMapPosition = mapPosition;
        }

        void IDFR_BattleAttackTargetModelTDSetter.Arrived() {
            m_IsArrived.Value = true;
            RemoveAllBuff();
        }

        void IDFR_BattleAttackTargetModelTDSetter.Dead() {
            OnDead?.Invoke();
        }

        void IDFR_BattleAttackTargetModelTDInternal.Initialize(DFR_BattleWayID wayID, Vector2F64 offset) {
            EditBegin();
            WayID = wayID;
            m_LastMapPosition = MapPosition;
            m_Offset = offset;
            EditDone();
        }
    }
}

namespace Internal.Runtime.Models {

    public interface IDFR_BattleAttackTargetModelTDInternal : IDFR_BattleAttackTargetModelBaseInternal {

        void Initialize(DFR_BattleWayID wayID, Vector2F64 offset);
    }
}


